package com.mrd.gtimp.business.service;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.stereotype.Service;

import com.mrd.base.BaseBiz;
import com.mrd.framework.utils.SpringUtils;
import com.mrd.gtimp.base.entity.Company;
import com.mrd.gtimp.base.service.CompanyBiz;
import com.mrd.gtimp.business.entity.Declaration;
import com.mrd.gtimp.business.entity.FundAccount;
import com.mrd.gtimp.business.entity.FundFlow;
import com.mrd.gtimp.v2.fund.FundFinancialTypeEnum;
import com.mrd.gtimp.v2.fund.FundIETypeEnum;
import com.mrd.spring.repository.BaseRepository;


/**
 * <p>
 * application name: gtimp
 * <p>
 * copyright: Copyright@2012 明睿达科技有限公司
 */

/**
 * @author luob
 */
@Service
public class FundFlowBiz extends BaseBiz<FundFlow> {

  @Resource
  private PaymentABCBiz paymentABCBiz;

  @Resource
  private CompanyBiz companyBiz;

  @Resource
  // 该处指定注入BaseRepository的dao对象
  @Qualifier("fundFlowDao")
  public void setBaseRepository(BaseRepository<FundFlow, String> baseRepository) {
    super.baseRepository = baseRepository;
  }


  public double findCurrentBalance(String comId) {
    double result = 0;
    /**
     * Filter filters = new Filter(); filters.setGroupOp(FilterGroupOption.AND); SearchRule rule =
     * new SearchRule("owner.id", SearchRuleOption.eq, comId); filters.addRule(rule); Sort.Order
     * order = new Sort.Order(Sort.Direction.DESC, "regDate"); try { List<FundFlow> results =
     * baseRepository.findEntityByFilter(1, 1, filters, order); result = results == null ? 0 :
     * results.size() > 0 ? results.get(0).getBalance() : 0; } catch (QueryException e) {
     * e.printStackTrace(); }
     */
    JdbcTemplate jdbcTemplate = SpringUtils.getBean(JdbcTemplate.class);
    StringBuilder sql =
        new StringBuilder("select BALANCE,ACC_VERSION from T_BIZ_FUND_ACCOUNT where COM_ID=?");
    Map<String, Object> acc =
        (Map<String, Object>) jdbcTemplate.queryForMap(sql.toString(), new Object[] {comId});
    result = new Double(acc.get("BALANCE").toString());// 当前余额
    DecimalFormat df = new DecimalFormat("######0.00");
    String _balance = df.format(result);
    return Double.parseDouble(_balance);
  }

  Logger log = Logger.getLogger(FundFlowBiz.class);

  @Transactional
  public FundFlow addFlow(FundFlow fundFlow) throws Exception {
    if (fundFlow == null || !StringUtils.isEmpty(fundFlow.getId()) || fundFlow.getOwner() == null) {
      throw new Exception(
          "fundFlow参数不符合要求[fundFlow == null || !StringUtils.isEmpty(fundFlow.getId()) || fundFlow.getOwner() == null]");
    }
    log.error("addFlow start:" + fundFlow);
    /*
     * if (StringUtils.isEmpty(fundFlow.getId())) { // 新增操作 Filter filters = new Filter();
     * filters.setGroupOp(FilterGroupOption.AND); SearchRule rule = new SearchRule("owner.id",
     * SearchRuleOption.eq, fundFlow .getOwner().getId()); filters.addRule(rule); int flowCount =
     * baseRepository.findEntityCount(filters); if (flowCount > 0) { String id =
     * UUID.randomUUID().toString().replaceAll("-", "");
     * baseRepository.excuteSql("INSERT into T_BIZ_FUND_FLOW" +
     * " (ID,COM_ID,AMOUNT,FINANCIAL_TYPE,IE_TYPE,BALANCE,REG_DATE,BILL_NO)" + " (SELECT '" + id +
     * "','" + fundFlow.getOwner().getId() + "'," + fundFlow.getAmount() + ",'" +
     * fundFlow.getFinancialType() + "','" + fundFlow.getIetype() + "', BALANCE+(" +
     * fundFlow.getFinancialAmount() + "), " + "TO_DATE('" + new
     * SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "','YYYY-MM-DD HH24:MI:SS'),'" +
     * fundFlow.getBillNo() + "' FROM (SELECT BALANCE, ROWNUM FROM T_BIZ_FUND_FLOW WHERE COM_ID='" +
     * fundFlow.getOwner().getId() + "' ORDER BY REG_DATE DESC) WHERE ROWNUM=1)", null);
     * fundFlow.setId(id); } else { fundFlow.setId(null); fundFlow.setRegDate(new Date());
     * fundFlow.setBalance(fundFlow.getFinancialAmount()); baseRepository.saveOrupdate(fundFlow);
     * List<FundFlow> dlist = baseRepository.findEntityByFilter(1, 1, filters, new
     * Sort.Order(Sort.Direction.DESC, "regDate")); if (dlist.size() == 1) { fundFlow =
     * dlist.get(1); } }
     * 
     * } else { // 修改操作
     * 
     * }
     */

    FundAccount fa = new FundAccount();
    // 修改账户信息
    boolean rtn = paymentABCBiz.changeFundAccBala(fundFlow, fa);
    if (rtn) {
      // 插入流水记录
      String flowId = String.valueOf(UUID.randomUUID());
      JdbcTemplate jdbcTemplate = SpringUtils.getBean(JdbcTemplate.class);
      jdbcTemplate.update(
          "insert into t_biz_fund_flow(id,com_id,amount,ie_type,FINANCIAL_TYPE,BALANCE,REG_DATE,BILL_NO) values (?, ?, ?, ?, ?, ?, ?, ?)",
          new PreparedStatementSetter() {
            public void setValues(PreparedStatement ps) throws SQLException {
              ps.setString(1, flowId);
              ps.setString(2, fa.getComId());
              ps.setDouble(3, fundFlow.getAmount());
              ps.setString(4, fundFlow.getIetype());
              ps.setString(5, fundFlow.getFinancialType());
              ps.setDouble(6, fa.getBalance());
              ps.setTimestamp(7, new java.sql.Timestamp(fa.getLastUpdDate().getTime()));
              ps.setString(8, fundFlow.getBillNo());
            }
          });
      fundFlow.setId(flowId);
      fundFlow.setOwner(companyBiz.findEntityById(fa.getComId()));
      fundFlow.setBalance(fa.getBalance());
    }
    log.error("addFlow end:" + fundFlow);
    return fundFlow;
  }


  public FundFlow addFlow(Company owner, double amount, FundIETypeEnum ieType, String billNo)
      throws Exception {
    FundFlow flow = new FundFlow();
    flow.setOwner(owner);
    flow.setAmount(amount);
    flow.setBillNo(billNo);
    flow.setIetype(ieType.toString());
    boolean ftype = (FundIETypeEnum.DC_INCOME.equals(ieType)
        || FundIETypeEnum.RECHARGE.equals(ieType) || FundIETypeEnum.ONLINE_RECHARGE.equals(ieType)
            | FundIETypeEnum.C_REJECT_FEE.equals(ieType));
    flow.setFinancialType(
        ftype ? FundFinancialTypeEnum.IN.toString() : FundFinancialTypeEnum.OUT.toString());
    flow.setRegDate(new Date());
    flow = addFlow(flow);
    return flow;
  }

  @Transactional
  public FundFlow addPayFlow(Company customer, double amount, FundIETypeEnum ieType, String billNo,
      Company supplier) throws Exception {
    FundFlow customerFlow = addFlow(customer, amount, ieType, billNo);
    addFlow(supplier, amount, FundIETypeEnum.DC_INCOME, billNo);
    return customerFlow;
  }

  public FundFlow addRejectFlow(Company customer, double amount, String billNo, Company supplier)
      throws Exception {
    FundFlow customerFlow = addFlow(customer, amount, FundIETypeEnum.C_REJECT_FEE, billNo);
    addFlow(supplier, amount, FundIETypeEnum.S_REJECT_FEE, billNo);
    return customerFlow;
  }


  /**
   * 报关单退款
   */
  public void declarationRefund(Declaration declaration) throws Exception {
    if (declaration == null || StringUtils.isEmpty(declaration.getId())) {
      throw new Exception("驳回出错！报关单信息为null！");
    }
    List<Object> fee = this.findObjectBySql(
        "select p.free from t_biz_fund_flow f left join t_biz_declara_free p on f.bill_no=p.pay_id where F.FINANCIAL_TYPE='OUT' and p.declaration_id=:did",
        0, 1, new HashMap<String, Object>() {
          {
            put("did", declaration.getId());
          }
        });

    if (fee == null || fee.isEmpty()) {
      throw new Exception("驳回出错！");
    }
    this.addFlow(declaration.getCustomer(), ((BigDecimal) fee.get(0)).doubleValue(),
        FundIETypeEnum.C_REJECT_FEE, declaration.getBusinessId());
    this.addFlow(declaration.getSupCompany(), ((BigDecimal) fee.get(0)).doubleValue(),
        FundIETypeEnum.S_REJECT_FEE, declaration.getBusinessId());

  }
}
